쿠버네티스 API 구조
개요
쿠버네티스를 다룰 때 kubectl을 이용하여 요청을 날리고는 한다.
또 이때 manifests라고 부르는 yaml 파일을 작성하여 전달을 하는데, 실제로 이것들은 어떤 구조로 이뤄진 것일까?
이 모든 요청들은 실제로 kube-apiserver가 처리하는데, 어떤 방식으로 api서버가 요청을 받아들이고 처리하는지 알아보자.
처음 공부할 때 간과하기 쉬운 게, api 서버를 조작하는 방법에 대한 것이다.
사실 이름만 봐도 알 수 있듯이, api 서버는 말그대로 Web Application Server, 그냥 WAS다.
그렇기 때문에 kubectl로 가하는 모든 조작은 사실 curl 같은 http 요청으로 똑같이 날릴 수가 있다.
개발 언어로 라이브러리를 쓸 때 역시 까보면 결국 api 요청을 날리는 식으로 환원된다는 것을 알 수 있다.
API 서버 접근
먼저 api 서버에 요청을 날릴 때 앞단에서 발생하는 일을 간단하게 본다.
api 서버니까 당연히 특정 주소에 특정 포트(기본 6443) api를 노출하고 있을 텐데, 아무나 접근하고 아무나 명령을 내릴 수 있는 것은 아니다.
이를 위해 api 서버에서 실제 요청이 수행되기 이전에 4가지의 단계가 일어난다.
자세한 내용은 시큐리티#API 서버 보안을 참고하자.
API 구조
모든 요청을 수행하는 것은 kube-apiserver이다.
이 api 서버에는 요청을 어떻게 날려야 하는가?
그냥 WAS일 뿐이라 실제로 curl https://{api server address}/ 이런 식으로 요청을 날리는 것이 가능하다.
근데 이 내부적으로 꽤나 정교하게 만들어진 하위 엔드포인트가 있다.
이를 명확히 하기 위해서 먼저 API 구조에 대해서 알아본다.
일단 가장 큰 범주에서 API는 두 가지로 구분지을 수 있다.
비 리소스(Non-resource)
아래 리소스에 해당하지 않는 모든 엔드포인트는 비 리소스로 간주된다.
클러스터에 대한 조작을 가하지 않거나, 클러스터 내부의 요소들에 대한 상태를 확인하지 않는 요청들이 여기에 해당한다.
대표적으로 /statusz, /healthz 등이 여기에 해당한다.
여기에 해당하는 것은 거의 없으니, 대체로 api라고 한다면 다음의 리소스를 생각해도 무방하다.
리소스(Resource)
리소스는 클러스터를 조작하거나 관리하는데 사용되는 모든 엔드포인트를 말한다.
이 엔드포인트에 각종 HTTP 메서드를 이용해 요청을 날리는 방식으로 api 서버를 조작하게 된다.
POST /api/v1/namespaces/default/pods
가령 default 네임스페이스에 파드를 만든다면, 이런 식으로 요청을 날리면 된다.
(바디에 파드 관련 스펙을 적어줘야 한다.)
개념 정리
명확한 용어 정의를 조금 더 내려보자.
- Resource Type
- 말 그대로 리소스 유형이다.
- 실제 URL에
pods,services와 같은 식으로 복수형으로 명시된다. - 일반 명사라고 이해하면 조금 더 편할 듯하다.
- 모든 리소스 유형은 저마다의 표현 형식이 지정돼있는데, 이 고정된 형식의 스키마를 kind라고 부른다.
- Resource
- Collection
- 복수 개의 리소스를 말한다.
- 이 표현 자체는 거의 쓸 일도 없고, URL에 이런 식으로 사용하는 방법도 없으니 그냥 개념적인 차원에서만 이해해도 좋다.
파드로 예를 들어본다면, 파드 자체는 리소스 유형이고, 그 중에서 A 파드 자체를 꼭 집어 말한다면 그것은 리소스이다.
그리고 여러 파드를 한꺼번에 표현한다면 그것은 컬렉션이라 부른다.
근데 뭐.. 실제로는 그냥 파드라 하면 우리는 흔히 리소스를 떠올리고 그렇게 표현하곤 한다.
그렇게 표현해도 어차피 의사소통에 그다지 문제될 게 없으니 개념을 이런 식으로 볼 수 있다고만 알고 있으면 된다.

참고로 굳이 컬렉션을 명시적으로 개념화한 이유는 이런 것 때문이다.
여러 개의 리소스를 조회하는 요청을 할 때 돌아오는 응답은 큰 kind가 {어떤 리소스}List가 되고, items필드에 어떤 리소스들의 원소가 들어가게 된다.
api 서버가 응답을 하는 값에는 이 컬렉션이 활용되기 때문에 이를 굳이 컬렉션이라고 부른다.
이 말을 듣고 kubectl에 -o json으로 명령을 내려본 당신, 막상 보니 kind가 List로 돼있을 것이다.
kubectl은 여러 개의 리소스 유형을 한꺼번에 조회하는 기능을 지원하기 때문에, 기본적으로 모든 아이템을 받은 후에 이를 List라는 kind로 출력해서 보여준다.
즉 그저 클라이언트 사이드에서만 kind: List가 있을 뿐, 실제로 api 서버에는 그런 kind가 없다는 것에 유의하자.
API 그룹
/api/v1/pods
/apis/apps/v1/deployments
/apis/apps/v1/namespaces/my-namespace/deployments/my-deployment
이 모든 리소스는 저마다 그룹에 속해있는데, 이를 API 그룹이라 부른다.
위의 예시에서, 파드 리소스 유형은 v1이라는 그룹에 속해있는 것이다.
그리고 디플로이먼트 리소스 유형은 apps/v1이라는 그룹에 속한다.
보다시피 API 그룹은 기본적으로 버전 정보와 어떤 역할을 한다던지에 대한 정보가 담긴다.
그럼 /api와 /apis는 무엇인가?
모든 리소스는 경로 상으로 /api나 /apis로 시작한다.
- api
- apis
- 네임드 그룹이라고 부르며, 여타 모든 리소스를 포함한다.
- 이들은 그룹과 버전에 대한 정보를 가지며,
/apis/{그룹 이름}/{버전}과 같은 형식으로 엔드포인트를 시작한다.
코어 그룹이라 하니 여기에만 클러스터에 필수적인 요소들이 들어갈 것만 같지만, 실상은 다르다.
네임드 그룹에는 현재 흔하디 흔하게 쓰이는 디플로이먼트, 인그레스, 컨피그맵 등 다양한 리소스들이 들어가 있다.
그래서 실질적으로 코어 그룹은 처음 쿠버네티스가 만들어질 당시 지정된 리소스들을 규정하는 방식의 잔재라고 보는 게 낫다.
kind
위에서 리소스 타입은 명확한 스키마자 정해져있다고 했는데, 그 스키마를 쿠버네티스에서는 kind라고 부른다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
가장 기본이 되는 파드의 양식을 이렇게 작성하는데, 이제 친숙한 것들이 눈에 띈다.
구조 정리
간단하게 도식을 정리하면 이렇게 볼 수 있다. 결론적으로 api 서버에 명령을 내려 클러스터를 조작하고 싶다면, 먼저 대상이 될 리소스를 지정한다. 그리고 그 리소스의 API 그룹과 버전을 앞단 경로로 작성하고, 리소스 유형을 적는다. (만약 특정 네임스페이스로 한정 짓고 싶다면 네임스페이스를 먼저 적어준다.) 그 다음에는 거기에 HTTP 메서드를 이용해서 명령을 내리면 되는 것이다! 이러한 방식을 쉽게 지원하는 명령줄 도구 중 하나가 바로 kubectl인 것이다.참고로 모든 api를 올인원으로 보고 싶다면 이 문서를 참고하자.[1]
API 확장
api 확장 방식에는 API Aggregation Layer, CRD가 있다.
미완성된 글입니다!!
추가 작성해야 하는 글입니다!!!
관련 문서
| 이름 | noteType | created |
|---|---|---|
| API 접근 제어 우회 | knowledge | 2025-01-13 |
| Authentication | knowledge | 2025-01-13 |
| Authorization | knowledge | 2025-01-19 |
| Prometheus-Adapter | knowledge | 2025-03-04 |
| kube-apiserver | knowledge | 2025-03-12 |
| 쿠버네티스 API 구조 | knowledge | 2025-03-19 |
| 클러스터 성능 최적화 | knowledge | 2025-08-30 |
| 6W - PKI 구조, CSR 리소스를 통한 api 서버 조회 | published | 2025-03-15 |
| 6W - api 구조와 보안 1 - 인증 | published | 2025-03-15 |
| 6W - EKS api 서버 접근 보안 | published | 2025-03-16 |
| E-api 서버 감사 | topic/explain | 2025-01-21 |